#include "Animation.h"

#include <cassert>

#include <SDL_rect.h>
#include <SDL_render.h>

#include <graphic/Drawer.h>
#include <graphic/DrawManager.h>
#include "utils/Error.h"
#include <main/Globals.h>
#include <utils\ResourceManager.h>

#include <iostream>

Animation::Animation(TextureData& texData, 
                     const uint32_t frameW,                      
                     const uint32_t frameH)
					 : mTexData(&texData)
{
    // Dimensions should be positive
    assert(frameW > 0);
    assert(frameH > 0);

    // Compute atlas dimensions
    // Check correctness according frame width and height
    {
        int w;
        int h;
        const int result = SDL_QueryTexture(mTexData->mTexture, 0, 0, &w, &h);
        if (result != 0) {
            printError("SDL_QueryTexture failed");
        }

        mAtlasW = static_cast<uint32_t> (w);
        mAtlasH = static_cast<uint32_t> (h);

        assert(mAtlasW >= frameW);
        assert(mAtlasH >= frameH);

        assert(mAtlasW % frameW == 0);
        assert(mAtlasH % frameH == 0);
    }    

	frameCount = mAtlasW / frameW * mAtlasH / frameH;

    // Initialize current frame
    mCurFrame.x = 0;
    mCurFrame.y = 0;
    mCurFrame.w = frameW;
    mCurFrame.h = frameH;

    mCurFrameCount = 0;

    mForwardPlay = true;
    mPlay = true;
    mPlayOnce = false;
    mDestroyable = false;

    mTexData->updateRect(mCurFrame);

    mFrameW = frameW;
    mFrameH = frameH;
}

// Reset animation to the first frame
void Animation::reset() {
    mCurFrame.x = 0;
    mCurFrame.y = 0;
    mCurFrameCount = 0;
    mTexData->updateRect(mCurFrame);
}

// Fill SDL_Rect with information about
// current frame rectangle
void Animation::currentFrameRect(SDL_Rect& rect) {
    rect = mCurFrame;
    mTexData->updateRect(mCurFrame);
}

// Update frame to the next one
void Animation::update() {
    if (!mPlay) {
        return;
    }    

    if (mForwardPlay) {
        // Because we assume frames are in row major order
        // we try to get the next animation in the current row
        // if we cannot, we go to the next column
        mCurFrame.x = (mCurFrame.x + mCurFrame.w) % mAtlasW;

        if (mCurFrame.x == 0) {
            mCurFrame.y = (mCurFrame.y + mCurFrame.h) % mAtlasH;
        }

        mCurFrameCount = (mCurFrameCount + 1) % frameCount;

        if (mCurFrameCount == 0 && mPlayOnce) {
            mPlay = false;
        }
    } else {
         
    }

    mTexData->updateRect(mCurFrame);

}

void Animation::playOnce(const bool destroyable) {
    mCurFrame.x = 0;
    mCurFrame.y = 0;
    mCurFrameCount = 0;
    mPlayOnce = true;  
    mForwardPlay = true;
    mDestroyable = destroyable;
}

void Animation::playOnceBackwards(const bool destroyable) {
    mCurFrame.x = 0;
    mCurFrame.y = 0;
    mCurFrameCount = 0;
    mPlayOnce = true;   
    mForwardPlay = false;
    mDestroyable = destroyable;
}